﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JBeamLibrary.Events;
using JBeamLibrary.VehicleParts.Elements;
using JBeamLibrary.VehicleParts.Interfaces;

namespace JBeamLibrary.VehicleParts.Collections
{
    public class TieCollection : KeyedCollection<string, Tie>, IVehicleGroupCollection<Tie>
    {
        #region Fields

        public event EventHandler<Tie> TieAdded;
        public event EventHandler TieRemoved;
        public event ElementPropertyChangedEventHandler ElementPropertyChanged;

        #endregion

        #region CTORs

        /// <summary>Creates a new tie collection</summary>
        public TieCollection()
        {

        }

        /// <summary>Creates a new tie collection</summary>
        /// <param name="ties"></param>
        public TieCollection(IEnumerable<Tie> ties)
        {
            AddRange(ties);
        }

        #endregion

        #region Methods
        /// <summary>Adds a tie</summary>
        /// <param name="tie"></param>
        public new void Add(Tie tie)
        {
            base.Add(tie);

            tie.PropertyChanged += (s, e) =>
            {
                if (ElementPropertyChanged != null)
                    ElementPropertyChanged(s, e);
            };

            if (TieAdded != null)
                TieAdded(this, tie);
        }

        /// <summary>Adds a collection of ties to the list</summary>
        /// <param name="ties"></param>
        public void AddRange(IEnumerable<Tie> ties)
        {
            foreach (var tie in ties)
                Add(tie);
        }

        /// <summary>Updates or adds the tie with the given node ID in the list</summary>
        /// <param name="nodeId"></param>
        /// <param name="maxLen"></param>
        /// <param name="rate"></param>
        /// <param name="shrt"></param>
        /// <param name="lng"></param>
        /// <param name="group"></param>
        /// <param name="maxForce"></param>
        public void UpdateAdd(string nodeId, float maxLen, float rate, float shrt, float lng, string group, long maxForce)
        {
            UpdateAdd(new Tie(nodeId, maxLen, rate, shrt, lng, group, maxForce));
        }

        /// <summary>Updates or adds the tie with a matching node ID in the list</summary>
        /// <param name="tie"></param>
        public void UpdateAdd(Tie tie)
        {
            if (Contains(tie.NodeId))
                Remove(tie.NodeId);
            Add(tie);
        }

        /// <summary>Updates or adds nodes of a given collection to the list</summary>
        /// <param name="ties"></param>
        public void UpdateAddRange(IEnumerable<Tie> ties)
        {
            foreach (var tie in ties)
                UpdateAdd(tie);
        }

        /// <summary>Removes a node</summary>
        /// <param name="tie"></param>
        public new void Remove(Tie tie)
        {
            base.Remove(tie);

            if (TieRemoved != null)
                TieRemoved(this, new EventArgs());
        }

        /// <summary>Removes the node at the specified index</summary>
        /// <param name="index"></param>
        public new void RemoveAt(int index)
        {
            base.RemoveAt(index);

            if (TieRemoved != null)
                TieRemoved(this, new EventArgs());
        }

        #endregion

        #region TieCollection

        protected override string GetKeyForItem(Tie item)
        {
            return item.NodeId;
        }

        #endregion
    }
}
